#include <iostream>
#include "task.hpp"
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string>
#include <vector>

class Channel
{
public:
    Channel(int wfd, pid_t pid, const std::string& name)
        :_wfd(wfd), _subPid(pid), _name(name)
    {}
    ~Channel() {}

    // get
    int GetWfd() { return _wfd; }
    pid_t GetSubPid() { return _subPid; }
    std::string GetName() {return _name; }

    void CloseChannel()
    {
        close(_wfd);
    }

    void Wait()
    {
        int rid = waitpid(_subPid, nullptr, 0);
        if (rid > 0)
        {
            std::cout << "wait: " << rid << ", sucess!" << std::endl; 
        }
    }

private:
    int _wfd;
    pid_t _subPid;
    std::string _name;
};


void CreateChannelAndSub(int num, std::vector<Channel>* channels, task_t task)
{
    for (int i = 0; i < num; i++)
    {
        // 1. 创建管道 
        int pipefd[2] = {0};
        int n = pipe(pipefd);
        if (n == -1) exit(1);

        // 2. 创建子进程
        pid_t id = fork();
        if (id == 0)
        {
            // child

            close(pipefd[1]); // 子进程关闭写文件
            dup2(pipefd[0], 0); // 将管道的读端，重定向到标准输入
            task(); // 将读端fd与work解耦
            close(pipefd[0]);
            exit(0);
        }

        // parent
        close(pipefd[0]);
        // 获得channel名字
        std::string name = "chnnel-" + std::to_string(i);
        // 父进程获得信道，只关心 wfd
        channels->push_back(Channel(pipefd[1], id, name));
    }
}

int NextChannel(int channelSize)
{
    static int cnt = 0;
    int ret = cnt;
    cnt++;
    cnt %= channelSize;
    return ret;
}

void ControlChannelOnce(std::vector<Channel>& channels)
{
    sleep(1);
    // a. 选择一个任务
    int taskcmd = SelectTask();
    // b. 选择一个信道下标
    int index_channel = NextChannel(channels.size());
    // c. 发送任务
    write(channels[index_channel].GetWfd(), &taskcmd, sizeof(taskcmd));
    
    std::cout << std::endl;
    std::cout << "taskcmd: " << taskcmd << ", channel: " << channels[index_channel].GetName() 
    << ", sub process: " << channels[index_channel].GetSubPid() << std::endl;
}

void ControlChannel(std::vector<Channel>& channels, int count = -1)
{
    if (count > 0)
    {
        while(count--)
            ControlChannelOnce(channels);
    }
    else
    {
        while(1)
            ControlChannelOnce(channels);
    }
}

void CleanChannel(std::vector<Channel>& channels)
{
    // 关闭写端，子进程的 read 会读到文件末尾，返回0
    for (auto& e : channels)
    {
        e.CloseChannel();
    }
    // 子进程已经结束进入僵尸状态，需要等待
    for (auto& e : channels)
    {
        e.Wait();
    }
}

int main(int argc, char* argv[])
{
    if (argc != 2)
    {
        std::cerr << "Usage: " << argv[0] << " ProcessNum" << std::endl;
    }

    int num = std::stoi(argv[1]); // 获得进程数
    LoadTask();

    // 1. 创建信道和进程
    std::vector<Channel> channels;
    CreateChannelAndSub(num, &channels, work); // 解耦，子进程回调work

    // 2. 父进程通过 channel 控制子进程
    ControlChannel(channels, 10);

    // 3. 关闭信道和子进程
    CleanChannel(channels);
    return 0;
}